package com.hezuti.common.structure.list;

public class DoubleLinkedList<T> {
	private DllNode<T> head;
	private long size;
	
	public DoubleLinkedList() {
		head = new DllNode<T>();
		size = 0;
	}
	
	public long size() {
		return size;
	}
	
	public void setSize(long size) {
		this.size = size;
	}
	
	synchronized public DllNode<T> addBefore(DllNode<T> curr, DllNode<T> node) {  
		node.add(curr, this);
		return node;
	}
	
	public DllNode<T> add(DllNode<T> node) {
		return addBefore(head, node);
	}
	
	public DllNode<T> add(T entry) {
		return addLast(entry);
	}
	
	public DllNode<T> addFirst(T entry) {
		return addBefore(head.next, new DllNode<T>(entry));
	}  
	
	public DllNode<T> addLast(T entry) {
		return addBefore(head, new DllNode<T>(entry));
	}
	
	synchronized public DllNode<T> remove(DllNode<T> curr) {
		curr.remove();
		return curr;
	}  
	
	public DllNode<T> remove(Object o) {  
		for(DllNode<T> p = head.next; p != head; p = p.next) {  
			if(o.equals(p.value)) {  
				return remove(p); 
			}
		}  
		return null;
	}
	
	public DllNode<T> removeFirst() {
		DllNode<T> node = head.next;
		if(node.next != node) {
			return remove(node);
		}
		return null;
	}
	
	public DllNode<T> removeLast() {
		DllNode<T> node = head.prev;
		if(node.prev != node) {
			return remove(node);
		}
		return null;
	}
	
	public DllNode<T> getFirst() {
		if(head.next != head) {
			return head.next;
		}
		return null;
	}
	
	public DllNode<T> getLast() {
		if(head.prev != head) {
			return head.prev;
		}
		return null;
	}
	
	synchronized public void clear() {
		head.next = head.prev = head;
		size = 0;
	}
	
	public void printList() {
		for(DllNode<T> p = head.next; p != head; p = p.next)
			System.out.println(p.value);
	}
	
	public static void main(String[] args) {
		DoubleLinkedList<String> t = new DoubleLinkedList<String>();
		t.add("a");
		t.add("b");
		t.add("c");
		System.out.println("1:"+t.size());
		t.addFirst("d");
		t.addLast("d");
		System.out.println("2:"+t.size());
		t.remove("d");
		System.out.println("3:"+t.size());
		t.printList();
		t.removeFirst();
		t.printList();
		t.removeLast();
		t.printList();
	}
}